package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author 程达
 * @PackageName:com.itheima.reggie.service.impl
 * @ClassName:DishServiceImpl
 * @Description:
 * @date 2022/5/25 16:32
 **/
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    //3.因为下面的方法里面 要使用 菜品口味保存方法
    @Autowired
    private DishFlavorService dishFlavorService;

    /**
     * 通过前端接受的数据 实现 菜品的保存 和 菜品口味的保存
     * <p>
     * 菜品信息的保存和口味信息的保存 是不可分割的单元,需要使用事务控制
     *
     * @param dishDto
     */
    @Override
    //3.进行了两次数据库的保存操作，操作了两张表，那么为了保证数据的一致性，
    //  我们需要在方法上加上注解 @Transactional来控制事务。
    @Transactional//	由于在 saveWithFlavor 方法中，进行了两次数据库的保存操作，
    // 操作了两张表，那么为了保证数据的一致性，我们需要在方法上加上注解 @Transactional来控制事务
    public void saveDishAndFlavor(DishDto dishDto) {
        log.info("[保存菜品信息和菜品风味信息]");
        //1:保存菜品基本信息①. 保存菜品基本信息 ;
        save(dishDto);// save(dish类型) 来自 mp 这是Service层的方法
        // 这个菜品信息id不是新增的吗 是
        // mp 这里 做添加之后 把 id回显回来
        //2: 保存菜品口味信息
        // 因为底层 搞属性 用的是 set get方法
        List<DishFlavor> flavors = dishDto.getFlavors();
        // 菜品口味信息
        // 某一个口味是不是属于某一个菜品
        // 前端传递过来的菜品口味 信息里面是不是没有菜品id
        // 遍历菜品口味列表 为菜品口味 加上 菜品id
        //③. 获取菜品口味列表，遍历列表，为菜品口味对象属性dishId赋值;
        if (flavors != null && flavors.size() > 0) {
            for (DishFlavor flavor : flavors) {
                //②. 获取保存的菜品ID ;
                flavor.setDishId(dishDto.getId());
            }
        }
        log.info("菜品口味,flavors:{}", flavors);
        // mybatisplus中有个批量添加方法
        /*
        // 插入（批量）
           boolean saveBatch(Collection<T> entityList);
         */
        // ④. 批量保存菜品口味列表; 给表中的字段一次插入多条数据(集合中的多个对象)
        dishFlavorService.saveBatch(flavors);
    }

    /**
     * 根据id查询菜品信息和对应的口味信息
     *
     * @param id
     * @return
     */
    @Override
    public DishDto getByIdWithFlavor(Long id) {
        log.info("[组装DishDto,根据id]"+id);
        //创建一个 准备返回的 DishDto = 菜品基本信息+关联的口味信息
        DishDto dishDto = new DishDto();
        // 1:去数据库根据id查询 菜品信息
        Dish dish = this.getById(id);//根据id查询菜品基本信息
        //2: 查询菜品关联菜品口味信息   --菜品id
        //条件查询 构建条件查询构造器
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,id);
        List<DishFlavor> flavors = dishFlavorService.list(wrapper);
        //3:  DishDto = 菜品基本信息+关联的口味信息
        //  菜品基本信息属性封装了吗   关联口味信息属性封装了吗
        BeanUtils.copyProperties(dish,dishDto);//基本属性赋值
        dishDto.setFlavors(flavors);
        return dishDto;
    }

    @Override
    @Transactional
    public void updateWithFlavor(DishDto dishDto) {
        //1: 对于dish菜品表  根据id更新基本信息
        updateById(dishDto);//其实传的是 dish 是dishDto的爹
        //2: 对于 dishflavor 表  根据菜品id 先删除所有管理的口味
        LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(DishFlavor::getDishId, dishDto.getId());//菜品id在dishDto
        //3.先删除再添加  ---中心思想
        dishFlavorService.remove(wrapper1);
        //3: 再进行新口味的添加
        //3: 保存菜品口味信息
        List<DishFlavor> flavors = dishDto.getFlavors();
        //给每个菜品口味加id
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishDto.getId());
        }
        log.info("加完id的菜品口味,flavors:{}", flavors);
        //批量添加
        dishFlavorService.saveBatch(flavors);
    }
}